<?php

namespace App\Services\SwitchPay;

use App\Caches\WechatH5PayCreateCache;
use App\Models\Orders;
use App\Services\PayMchService;
use App\Services\WechatApi\UnifiedOrder\UnifiedOrder;
use App\Services\WechatApi\WechatApiOauth;
use Illuminate\Http\Request;

/**
 * 微信H5网页支付
 * 接入文档: https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1
 * 需要先创建好微信商户平台账号，在申请H5支付里，要配置授权支付域名，而且此域名必须经过备案，否则将出现无法拉起支付
 * 提示: 商家存在未配置的参数，请联系商家解决
 */
class WxpayH5 extends SwitchPayBase
{
    protected $wxpayConfig;

    function __construct($pay_platform, $game_id, $game_channel_id)
    {
        parent::__construct($pay_platform, $game_id, $game_channel_id);

        $wxpay_name = $this->gameChannel['wxh5_pay'];
        $this->wxpayConfig = PayMchService::getInstance()->getByName($wxpay_name);
        $this->wxpayConfig['notify_url'] = $this->callbackUrl();
        $this->wxpayConfig['return_url'] = $this->callbackCpUrl();
    }

    // 支付成功后端异步回调
    public function callbackUrl()
    {
        $host = $this->wxpayConfig['host'] ?? config('app.url');
        return "{$host}/api/switch_pay/callback/{$this->payPlatform}/" . $this->gameChannel['id'];
    }

    // 支付成功前端回调
    public function callbackCpUrl()
    {
        $host = $this->wxpayConfig['host'] ?? config('app.url');
        return "{$host}/api/switch_pay/callback/{$this->payPlatform}/" . $this->gameChannel['id'];
    }

    // 支付结果页面url
    public function payRedirectUrl(Orders $order)
    {
        $host = $this->wxpayConfig['host'] ?? config('app.url');
        $url = "{$host}/switch_pay/info/{$order->trade_no}";

        return $url;
    }

    // 公众号支付链接
    private function getWxJsPayUrl($order)
    {
        $appid = $this->gameChannel['jspay_appid'];
        $trade_no = $order->trade_no;
        $cb_url = config('app.url') . "/wxpay_jssdk_access_token?trade_no={$trade_no}";
        $url = WechatApiOauth::getInstance()->getUserOauthUrl($appid, $cb_url, 'snsapi_base', 'pay');
        return $url;
    }

    private function getWxH5PayUrl($order)
    {
        $trade_no = $order->trade_no;
        $host = $this->wxpayConfig['host'] ?? config('app.url');
        $url = "{$host}/wxpay_h5?trade_no={$trade_no}";
        return $url;
    }

    /**
     * 创建订单-渠道信息整理返回
     * @param Orders  $order   订单模型
     * @param Request $request 请求参数
     */
    public function payInit(Orders $order, Request $request)
    {
        $trade_no = $order->trade_no;
        $cache = WechatH5PayCreateCache::getInstance()->get($trade_no);
        if (!empty($cache)) {
            return yqok($cache);
        }

        // 扫码支付走公众号
        $is_qrcode_pay = $request->input('qrcode_pay') ?? 0;
        if ($is_qrcode_pay == 1) {
            $jump_qrcode_url = $this->getWxJsPayUrl($order);
            $data = [
                'jump_qrcode_url' => $jump_qrcode_url,
            ];

            return yqok($data);
        }

        // 统一下单
        $attach = $order->game_id;
        $body   = $order->money;
        $params = [
            'body'         => $body,
            'out_trade_no' => $order->trade_no,
            'total_fee'    => ceil($order->money * 100),
            'notify_url'   => $this->wxpayConfig['notify_url'],
            'attach'       => $attach,
            'scene_info'   => json_encode(['h5_info' => ['type' => 'Wap', 'wap_url' => config('app.url'), 'wap_name' => lang(60001)]]),
        ];
        $res = UnifiedOrder::getInstance()->createOrder($this->wxpayConfig['appid'], $this->wxpayConfig['mch_key'], $this->wxpayConfig['mch_id'], 'MWEB', $params);
        if ($res === false) {
            return yqerr(6027);
        }
        $mweb_url = $res['mweb_url'];

        // 由于设置 redirect_url 后,回跳指定页面的操作可能发生在：
        // 1,微信支付中间页调起微信收银台后超过5秒
        // 2,用户点击“取消支付“
        // 3,支付完成后点“完成”按钮。
        $data = [
            'mweb_url'     => $mweb_url,
            'redirect_url' => $this->payRedirectUrl($order),
            'message'      => $this->getWxH5PayUrl($order)
        ];

        WechatH5PayCreateCache::getInstance()->update($trade_no, $data);

        // yqlog($data);

        // return view('pay.wxh5', $data);
        return yqok($data);
    }

    /**
     * 处理充值回调 由于接口已经处理了成功和失败返回，所以后面的 payErr 和 payOk 无需再进行返回任何内容，否则微信认为返回有误可能导致
     * 微信单方面认为丢单，不给于对账
     * @param Request $request 请求参数
     * @param string  $cb_type 谁回调过来 server,client
     * @return void|string      返回第三方订单
     */
    public function payCb(Request $request, $cb_type)
    {
        $notify = $this->payNotify;

        $xml = file_get_contents('php://input');
        $res = UnifiedOrder::getInstance()->payNotify($this->wxpayConfig['mch_key'], $xml);
        if (!$res) {
            $notify->errno = 6023;
            return $notify;
        }

        // 微信用户唯一标识
        $openid = $res['openid'];
        // 我方订单
        $trade_no = $res['out_trade_no'];
        // 微信订单
        $channel_trade_no = $res['transaction_id'];
        // 订单金额 分
        $total_fee = $res['total_fee'];

        // 校验订单
        $order = Orders::where('trade_no', $trade_no)->first();
        if (!$order) {
            $notify->errno = 6020;
            return false;
        }

        // 校验充值金额
        if (abs($order->money - $total_fee / 100) > 1) {
            $notify->errno = 6024;
            return false;
        }

        $notify->order          = $order;
        $notify->tradeNo        = $trade_no;
        $notify->channelTradeNo = $channel_trade_no;
        $notify->mchId          = $this->wxpayConfig['mch_id'];
        $notify->openid         = $openid;

        return $notify;
    }

    // 失败返回
    public function payErr()
    {
        $notify = $this->payNotify;
        $xml = UnifiedOrder::getInstance()->payNotifyReturn($this->wxpayConfig['mch_key'], 'FAIL', lang($notify->errno));
        return $xml;
    }

    // 成功返回
    public function payOk()
    {
        $xml = UnifiedOrder::getInstance()->payNotifyReturn($this->wxpayConfig['mch_key'], 'SUCCESS', 'OK');
        return $xml;
    }
}
